package com.bolins.examples.subspringside.mongodb;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.bson.types.ObjectId;

import com.google.common.collect.Lists;
import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBObject;
import com.mongodb.gridfs.GridFS;
import com.mongodb.gridfs.GridFSDBFile;
import com.mongodb.gridfs.GridFSInputFile;

/**
 * Mongod Service 接口实现
 * 
 * @author liuys
 * 
 */
public class MongodServiceSupport implements MongodService {

	private String dbName;
	private String collName;
	private DB db;

	public MongodServiceSupport(String dbName, String collName) {
		this.dbName = dbName;
		this.collName = collName;
		db = MongoDBConfig.getDB(this.dbName);
	}

	public void delete(Map<String, Object> map) {
		DBObject obj = MongoDBUtils.mapToDBObj(map);
		getCollection().remove(obj);
	}

	public void deleteBatchWithMap(List<Map<String, Object>> list) {
		if (list == null || list.isEmpty())
			return;

		DBObject obj = null;
		for (Map<String, Object> map : list) {
			obj = MongoDBUtils.mapToDBObj(map);
			getCollection().remove(obj);
		}
	}

	@SuppressWarnings("unchecked")
	public List<Map<String, Object>> find(Map<String, Object> map) {
		DBObject object = MongoDBUtils.mapToDBObj(map);
		Iterator<DBObject> it = getCollection().find(object).iterator();

		List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
		while (it.hasNext()) {
			list.add(it.next().toMap());
		}
		return list;
	}

	@SuppressWarnings("unchecked")
	public List<Map<String, Object>> findAll() {
		Iterator<DBObject> it = getCollection().find().iterator();
		List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();

		while (it.hasNext()) {
			list.add(it.next().toMap());
		}
		return list;
	}

	public List<GridFSDBFile> findFilesByName(String fileName) {
		return getGridFS().find(fileName);
	}

	public GridFSDBFile findFirstFile(Map<String, Object> map) {
		return getGridFS().findOne(MongoDBUtils.mapToDBObj(map));
	}

	public List<GridFSDBFile> getAllFiles() {
		return getGridFS().find(new BasicDBObject());
	}

	@SuppressWarnings("unchecked")
	public Map<String, Object> getById(String id) {
		DBObject filter = new BasicDBObject();
		filter.put("id", Long.valueOf(id));
		return getCollection().findOne().toMap();
	}

	public long getCollectionCount() {
		return getCollection().count();
	}

	public String getCollectionName() {
		return this.collName;
	}

	public long getCount(Map<String, Object> map) {
		DBObject obj = MongoDBUtils.mapToDBObj(map);
		return getCollection().find(obj).count();
	}

	public DB getDB() {
		return this.db;
	}

	public DBCollection getCollection() {
		return db.getCollection(this.collName);
	}

	public String getDBName() {
		return this.dbName;
	}

	public List<String> getDBNames() {
		return MongoDBConfig.getDBNames();
	}

	public long getFileCount() {
		return getGridFS().getFileList().itcount();
	}

	public InputStream getFileInputStream(String fileName) {
		return getGridFS().findOne(fileName).getInputStream();
	}

	public GridFS getGridFS() {
		return new GridFS(db);
	}

	public void insert(Map<String, Object> map) {
		DBObject obj = MongoDBUtils.mapToDBObj(map);
		getCollection().insert(obj);
	}

	public void insertBatchWithMap(List<Map<String, Object>> list) {
		if (list == null || list.isEmpty())
			return;

		List<DBObject> objects = Lists.newArrayList();
		for (Map<String, Object> map : list) {
			objects.add(MongoDBUtils.mapToDBObj(map));
		}

		getCollection().insert(objects);
	}

	public void removeAllFile() {
		getGridFS().remove(new BasicDBObject());
	}

	public void removeFile(BasicDBObject object) {
		getGridFS().remove(object);
	}

	public void removeFile(ObjectId id) {
		getGridFS().remove(id);
	}

	public void removeFile(String fileName) {
		getGridFS().remove(fileName);
	}

	public void saveFile(byte[] bytes, String fileName) {
		GridFS fs = getGridFS();
		GridFSInputFile fi = fs.createFile(bytes);
		fi.put("fileName", fileName);
		fi.save();
	}

	public void saveFile(File file, String fileName) {
		GridFS fs = getGridFS();

		try {
			GridFSInputFile fi = fs.createFile(file);
			fi.put("fileName", fileName);
			fi.put("uploadDate", new Date());
			fi.save();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public void saveFile(InputStream is, String fileName) {
		GridFS fs = getGridFS();
		GridFSInputFile fi = fs.createFile(is, fileName);
		fi.save();
	}

	public void setCollectionName(String coll) {
		this.collName = coll;
	}

	public void setDB(DB db) {
		this.db = db;
	}

	public void setDBName(String db) {
		this.dbName = db;
	}

	public void update(Map<String, Object> setFields,
			Map<String, Object> whereFields) {
		DBObject q = MongoDBUtils.mapToDBObj(setFields);
		DBObject o = MongoDBUtils.mapToDBObj(whereFields);
		getCollection().update(q, o);
	}

	public void delete(Restrictions rests) {
		getCollection().remove(MongoDBUtils.restrictionsToDBObject(rests));
	}

	public void deleteBatchWithRestrictions(List<Restrictions> list) {
		if (list == null || list.isEmpty())
			return;

		for (Restrictions rest : list) {
			getCollection().remove(MongoDBUtils.restrictionsToDBObject(rest));
		}
	}

	@SuppressWarnings("unchecked")
	public List<Map<String, Object>> find(Restrictions rests) {
		DBObject object = MongoDBUtils.restrictionsToDBObject(rests);

		Iterator<DBObject> it = getCollection().find(object).iterator();

		List<Map<String, Object>> list = Lists.newArrayList();
		while (it.hasNext()) {
			list.add(it.next().toMap());
		}
		return list;
	}

	public GridFSDBFile findFirstFile(Restrictions rests) {
		return getGridFS().findOne(MongoDBUtils.restrictionsToDBObject(rests));
	}

	public void insert(Restrictions rests) {
		getCollection().insert(MongoDBUtils.restrictionsToDBObject(rests));
	}

	public void insertBatchWithRestrictions(List<Restrictions> list) {
		if (list == null || list.isEmpty())
			return;

		List<DBObject> objects = Lists.newArrayList();
		for (Restrictions rests : list) {
			objects.add(MongoDBUtils.restrictionsToDBObject(rests));
		}

		getCollection().insert(objects);
	}

	public void update(Restrictions setFilds, Restrictions whereFields) {
		DBObject q = MongoDBUtils.restrictionsToDBObject(setFilds);
		DBObject o = MongoDBUtils.restrictionsToDBObject(whereFields);
		getCollection().update(q, o);
	}

}
